package net.mengkang;


import com.alibaba.fastjson2.JSON;
import net.mengkang.utils.TraceUtil;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public class DispatcherServlet extends HttpServlet {

    private String controllerScan;

    private Map<String, Method> mappingRegistry = new HashMap<>();

    public DispatcherServlet(String controllerScan) {
        this.controllerScan = controllerScan;
        initMappingRegistry();
    }

    private void initMappingRegistry() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        URL url = classLoader.getResource(controllerScan.replace(".", "/"));
        File file = new File(url.getFile());

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File controller : files) {
                String fileName = controller.getAbsolutePath();
                String className = fileName.substring(fileName.indexOf(controllerScan.replace(".", "/")), fileName.indexOf(".class")).replace("/", ".");

                try {
                    Class<?> clazz = classLoader.loadClass(className);
                    Method[] methods = clazz.getDeclaredMethods();
                    for (Method method : methods) {
                        System.out.println(fileName + " " + method.getName());

                        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);

                        if (requestMapping == null) {
                            continue;
                        }

                        mappingRegistry.put(requestMapping.method().name() + requestMapping.value(), method);
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String requestInfo = RequestMethod.GET.name() + request.getRequestURI();

        System.out.println(requestInfo);

        if (mappingRegistry.containsKey(requestInfo)) {
            Method method = mappingRegistry.get(requestInfo);

            try {
                Object res = method.invoke(method.getDeclaringClass().newInstance());

                PrintWriter printWriter = response.getWriter();
                String data = JSON.toJSONString(res);
                System.out.printf("time:%s traceId:%s %s\n", System.currentTimeMillis(), TraceUtil.get(), data);
                printWriter.println(data);

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }

}
